package redis;

import redis.clients.jedis.Jedis;

import java.util.Collections;

/**
 * Created by sunyuming on 19/8/2.
 */
public class RedisLock {

    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";

    /**
     * 尝试获取分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁
     * @param requestId 请求标识
     * @param expireTime 超期时间
     * @return 是否获取成功
     */
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {

        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);

        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }

    private static final Long RELEASE_SUCCESS = 1L;

    /**
     * 释放分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁
     * @param requestId 请求标识
     * @return 是否释放成功
     */
    public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {

        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));

        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }

    public static void main(String [] f) {

        final String lockValue1 = "sun1";
        final String lockValue2 = "sun2";
        final String lockKey = "templock1346";

        // 10s redis 连接超时
        Jedis jedis = new Jedis("10.161.228.88", 6379, 10000);
        jedis.auth("test");
        Boolean lock = null;
        Boolean unlock = null;
        while (true) {
            // 锁20s
            lock = tryGetDistributedLock(jedis, lockKey, lockValue1, 20000);
            if(lock) {
                System.out.println("取得锁");

                // 此句模拟视图释放其它线程的锁
            //    jedis.set(lockKey, lockValue2);
                unlock = releaseDistributedLock(jedis, lockKey, lockValue1);
                if(unlock) {
                    System.out.println("释放成功");
                } else {
                    System.out.println("释放失败");
                }
                break;
            } else {
                System.out.println("未获取锁");
            }

            // 100ms轮训自旋
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


    }
}
